﻿#include "NosepieceOUMIT.h"
#include <QTextStream>


extern "C"
{

Qly::NosepieceInterface * CreateInstance(QObject *parent)
{
    Qly::NosepieceOUMIT *p = new Qly::NosepieceOUMIT(parent);
    return p;
}

 void Release(Qly::NosepieceInterface * p)
{
     if( dynamic_cast<Qly::NosepieceOUMIT*>(p) != nullptr)
    {
        delete p;
    }
}

}

namespace Qly {

NosepieceOUMIT::NosepieceOUMIT(QObject *parent)
    : NosepieceInterface(parent)
{
//    m_pTimer = new QTimer(this);
//    m_pTimer->setInterval(500);
//    connect(m_pTimer, &QTimer::timeout, this, &NosepieceOUMIT::on_timeout);

}

NosepieceOUMIT::~NosepieceOUMIT()
{
    close();
}

void NosepieceOUMIT::open()
{
    if(m_pSerialPort)
    {
        m_pSerialPort->close();
        disconnect(m_pSerialPort);
        delete m_pSerialPort;
    }
    m_pSerialPort = new QSerialPort(m_comPort, this);
    connect(m_pSerialPort, &QSerialPort::readyRead, this, &NosepieceOUMIT::on_readyRead);
    if(m_pSerialPort->open(QIODevice::ReadWrite))
    {
        m_pSerialPort->setBaudRate(m_baudRate);
        m_pSerialPort->setDataBits(static_cast<QSerialPort::DataBits> (m_dataBits));
        m_pSerialPort->setParity(static_cast<QSerialPort::Parity>(m_parity));
        m_pSerialPort->setStopBits(static_cast<QSerialPort::StopBits>(m_stopBits));
        m_pSerialPort->setFlowControl(QSerialPort::NoFlowControl);
        m_pSerialPort->clearError();
        m_pSerialPort->clear();
        qDebug() << "NosepieceOUMIT open serial port ok!";
//        m_pTimer->start();
    }
    else
    {
        qWarning() << "NosepieceOUMIT open Serial Port failed";
    }
}

void NosepieceOUMIT::close()
{
    if(m_pTimer) m_pTimer->stop();
    if(m_pSerialPort)
    {
        m_pSerialPort->close();
        disconnect(m_pSerialPort, &QSerialPort::readyRead, this, &NosepieceOUMIT::on_readyRead);
        delete m_pSerialPort;
        m_pSerialPort = nullptr;
    }
}

void NosepieceOUMIT::on_timeout()
{
//    uint8_t cmd[] = {0x5A, 0xA5, 0x06, 0x84, 0x10, 0x03, 0x01, 0x00, 0x00, 0x9E};
//    m_pSerialPort->write((char *)cmd, 10);
}

void NosepieceOUMIT::on_readyRead()
{
    QByteArray array = m_pSerialPort->readAll();
    qDebug() << array << ", m_state = " << m_state;

    auto it = array.begin();
    while(it != array.end())
    {
        stateMachine(*it);
        ++it;
    }
    qDebug() << "m_state = " << m_state;
}

void NosepieceOUMIT::stateMachine(uint8_t data)
{
    switch (m_state) {
    case 0:
        if(data == 0x5A) m_state = data;
        else if(data == 0xA5) m_state = data; // 解决少收一个字符的问题
        break;

    case 0x5A:
        if(data == 0xA5) m_state = data;
        else
        {
            qDebug() << "bad data";
            m_state = 0;
        }
        break;

    case 0xA5:
        if(data == 0x03) m_state = data;
        else
        {
            qDebug() << "bad data";
            m_state = 0;
        }
        break;

    case 0x03:
        if(data == 0x82) m_state = data;
        else
        {
            qDebug() << "bad data";
            m_state = 0;
        }
        break;

    case 0x82:
        if(data == 0x4F) m_state = data;
        else
        {
            qDebug() << "bad data";
            m_state = 0;
        }
        break;

    case 0x4F:
        if(data == 0x4B) m_state = data;
        else
        {
            qDebug() << "bad data";
            m_state = 0;
        }
        break;

    case 0x4B:
        m_state = 0;
        uint8_t lens = m_maxLensCount - data;

//        qDebug() << "Here";
        if(data <= 6)// && lens != m_lensIndex)
        {
            uint8_t oldLens = m_lensIndex;
            m_lensIndex = lens;

            qDebug() << "NosepieceOUMIT::stateMachine:: emit lensChanged(" << oldLens << ", " << lens << ") (OUMIT lens = " << data << ")";
            emit lensChanged(oldLens, lens);
        }
        break;
    }

}

void NosepieceOUMIT::loadSettings(QSettings &settings)
{
    m_comPort = settings.value("NosepieceOUMIT/SerialPort", "COM1").toString();
    m_baudRate = settings.value("NosepieceOUMIT/BaudRate", QSerialPort::Baud115200).toInt();
    m_dataBits = settings.value("NosepieceOUMIT/DataBits", QSerialPort::Data8).toInt();
    m_parity = settings.value("NosepieceOUMIT/Parity", QSerialPort::NoParity).toInt();
    m_stopBits = settings.value("NosepieceOUMIT/StopBits", QSerialPort::OneStop).toInt();
    m_maxLensCount = settings.value("NosepieceOUMIT/LensCount", 5).toInt();
    m_lensIndex = settings.value("NosepieceOUMIT/lens", 0).toInt();
    open();
}

void NosepieceOUMIT::writeSettings(QSettings &settings)
{
    settings.setValue("NosepieceOUMIT/lens", m_lensIndex);
}

void NosepieceOUMIT::setSerialPort(QString comm, int baudRate, int dataBits, int parity, int stopBits)
{
    m_comPort = comm;
    m_baudRate = baudRate;
    m_dataBits = dataBits;
    m_parity = parity;
    m_stopBits = stopBits;
}

void NosepieceOUMIT::setMaxIndex(int maxIndex)
{
    m_maxLensCount = maxIndex;
}

void NosepieceOUMIT::setLens(int lens)
{
    qDebug() << "NosepieceOUMIT::setLens:: lens = " << lens;
    if(lens == m_lensIndex) return;
    m_lensIndex = lens;

    uint8_t cmd[] = {0x5A, 0xA5, 0x06, 0x83, 0x10, 0x03, 0x01, 0x00, 0x01, 0x9E};
    switch (m_maxLensCount - lens - 1)
    {
    case 0:
        cmd[8] = 0x01;
        cmd[9] = 0x9E;
        break;
    case 1:
        cmd[8] = 0x02;
        cmd[9] = 0x9F;
        break;
    case 2:
        cmd[8] = 0x03;
        cmd[9] = 0xA0;
        break;
    case 3:
        cmd[8] = 0x04;
        cmd[9] = 0xA1;
        break;
    case 4:
        cmd[8] = 0x05;
        cmd[9] = 0xA2;
        break;
    case 5:
        cmd[8] = 0x06;
        cmd[9] = 0xA3;
        break;
    default:
        return;
        break;
    }
    QByteArray array((const char *)cmd, 10);
    qDebug() << "NosepieceOUMIT::setLens SerialPort->write " << array;

    m_pSerialPort->write((char *)cmd, 10);

}

void NosepieceOUMIT::setLens(int oldLens, int newLens)
{
    Q_UNUSED(oldLens);
    setLens(newLens);
}

void NosepieceOUMIT::forward()
{
    if(m_lensIndex < m_maxLensCount)
    {
        setLens(m_lensIndex + 1);
    }
}

void NosepieceOUMIT::reverse()
{
    if(m_lensIndex > 0)
    {
        setLens(m_lensIndex - 1);
    }
}

void NosepieceOUMIT::showSetupDialog()
{

}

}
